// src/pages/StockMinuteWithIndicators/StockMinuteWithIndicators.jsx

import React, { useEffect, useRef, useState } from 'react';
import * as echarts from 'echarts';
import {
  Card,
  Input,
  Select,
  Spin,
  message,
  Checkbox,
  Row,
  Col,
} from 'antd';
import { $fetchAStockMinute } from '../../api/stockApi';
import './StockMinuteWithIndicators.scss';

const { Search } = Input;
const { Option } = Select;

// 指标可选项
const INDICATORS = [
  { label: 'MA (5,10,20)', value: 'MA' },
  { label: 'MACD', value: 'MACD' },
  { label: 'RSI', value: 'RSI' },
  { label: 'KDJ', value: 'KDJ' },
  { label: 'BOLL', value: 'BOLL' },
];

const StockMinuteWithIndicators = () => {
  const chartRef = useRef(null);
  const chartInstance = useRef(null);

  const [symbol, setSymbol] = useState('sh600519'); // 默认股票
  const [period, setPeriod] = useState('1'); // 默认 1 分钟
  const [loading, setLoading] = useState(false);
  const [indicators, setIndicators] = useState([]); // 当前勾选的指标

  // 原始分钟线数据
  const [minuteData, setMinuteData] = useState([]); // 每条 { time, open, high, low, close, volume }

  /** 
   * 计算 MA
   * @param {number[]} arr - 收盘价数组 
   * @param {number} n - 周期
   * @returns {Array<number|null>} 长度与 arr 一致，如果前 n 条不足，值为 null
   */
  const calcMA = (arr, n) => {
    const res = [];
    for (let i = 0; i < arr.length; i++) {
      if (i < n - 1) {
        res.push(null);
      } else {
        let sum = 0;
        for (let j = i - n + 1; j <= i; j++) {
          sum += arr[j];
        }
        res.push(parseFloat((sum / n).toFixed(4)));
      }
    }
    return res;
  };

  /**
   * 计算 EMA（用于 MACD 里计算 EMA12, EMA26）
   * @param {number[]} arr - 收盘价数组
   * @param {number} n - 周期
   * @returns {Array<number|null>}
   */
  const calcEMA = (arr, n) => {
    const res = [];
    const alpha = 2 / (n + 1);
    let prevEMA = null;
    for (let i = 0; i < arr.length; i++) {
      const price = arr[i];
      if (i === 0) {
        prevEMA = price;
        res.push(parseFloat(price.toFixed(4)));
      } else {
        const currEMA = alpha * price + (1 - alpha) * prevEMA;
        res.push(parseFloat(currEMA.toFixed(4)));
        prevEMA = currEMA;
      }
    }
    return res;
  };

  /**
   * 计算 MACD：DIF, DEA, MACD 柱状
   * @param {number[]} closeArr - 收盘价数组
   * @returns {{ DIF: number[], DEA: number[], MACD: number[] }}
   */
  const calcMACD = (closeArr) => {
    const ema12 = calcEMA(closeArr, 12);
    const ema26 = calcEMA(closeArr, 26);
    const DIF = [];
    for (let i = 0; i < closeArr.length; i++) {
      const v = ema12[i] != null && ema26[i] != null ? ema12[i] - ema26[i] : null;
      DIF.push(v != null ? parseFloat(v.toFixed(4)) : null);
    }
    // DEA 为 DIF 的 9 周期 EMA
    const validDIF = DIF.map((v) => (v == null ? 0 : v));
    const deaRaw = calcEMA(validDIF, 9);
    // MACD = 2 * (DIF - DEA)
    const DEA = deaRaw.map((v) => parseFloat(v.toFixed(4)));
    const MACD = DIF.map((v, i) => {
      if (v == null || DEA[i] == null) return null;
      return parseFloat((2 * (v - DEA[i])).toFixed(4));
    });
    return { DIF, DEA, MACD };
  };

  /**
   * 计算 RSI
   * @param {number[]} closeArr - 收盘价数组
   * @param {number} n - 周期，默认为14
   * @returns {Array<number|null>}
   */
  const calcRSI = (closeArr, n = 14) => {
    const res = [];
    let gains = 0,
      losses = 0;
    for (let i = 1; i < closeArr.length; i++) {
      const change = closeArr[i] - closeArr[i - 1];
      gains += Math.max(change, 0);
      losses += Math.max(-change, 0);
      if (i < n) {
        res.push(null);
      } else if (i === n) {
        const avgGain = gains / n;
        const avgLoss = losses / n;
        const rsi = avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss);
        res.push(parseFloat(rsi.toFixed(2)));
        // 接下来用平滑公式
      } else {
        const prevRSI = res[i - 1];
        // 重新计算当期 gain/loss
        const change2 = closeArr[i] - closeArr[i - 1];
        const gain = Math.max(change2, 0);
        const loss = Math.max(-change2, 0);
        // 平滑
        const prevAvgGain = (res[i - 1] != null && i - 1 >= n)
          ? ((closeArr[i - (n - 1)] - closeArr[i - n] > 0
              ? closeArr[i - (n - 1)] - closeArr[i - n]
              : 0) + (n - 1) * (100 - 100 / (1 + (gains / n) / (losses / n))) / 100 * (i > n ? (100 - 100 / (1 + (gains / n) / (losses / n))) : 0))
          : null;
        // 这里为了简单，用基本的 Wilder 公式：
        const prevAvgGain2 = gains / n;
        const prevAvgLoss2 = losses / n;
        const currAvgGain = (prevAvgGain2 * (n - 1) + gain) / n;
        const currAvgLoss = (prevAvgLoss2 * (n - 1) + loss) / n;
        const currRSI = currAvgLoss === 0
          ? 100
          : 100 - 100 / (1 + currAvgGain / currAvgLoss);
        res.push(parseFloat(currRSI.toFixed(2)));
        gains = currAvgGain * n; // 还原 Wilder 计算下一步
        losses = currAvgLoss * n;
      }
    }
    // 补齐首位 null
    res.unshift(null);
    return res;
  };

  /**
   * 计算 KDJ
   * @param {number[]} highArr
   * @param {number[]} lowArr
   * @param {number[]} closeArr
   * @param {number} n - 期数，默认 9
   * @returns {{ K: number[], D: number[], J: number[] }}
   */
  const calcKDJ = (highArr, lowArr, closeArr, n = 9) => {
    const len = closeArr.length;
    const K = [];
    const D = [];
    const J = [];
    let prevK = 50;
    let prevD = 50;
    for (let i = 0; i < len; i++) {
      if (i < n - 1) {
        K.push(null);
        D.push(null);
        J.push(null);
      } else {
        // 计算过去 n 根的最低价和最高价
        const highSlice = highArr.slice(i - (n - 1), i + 1);
        const lowSlice = lowArr.slice(i - (n - 1), i + 1);
        const highest = Math.max(...highSlice);
        const lowest = Math.min(...lowSlice);
        const rsv =
          highest === lowest
            ? 50
            : ((closeArr[i] - lowest) / (highest - lowest)) * 100;
        const currK = (2 / 3) * prevK + (1 / 3) * rsv;
        const currD = (2 / 3) * prevD + (1 / 3) * currK;
        const currJ = 3 * currK - 2 * currD;
        K.push(parseFloat(currK.toFixed(2)));
        D.push(parseFloat(currD.toFixed(2)));
        J.push(parseFloat(currJ.toFixed(2)));
        prevK = currK;
        prevD = currD;
      }
    }
    return { K, D, J };
  };

  /**
   * 计算 BOLL（布林带）
   * @param {number[]} closeArr
   * @param {number} n - 期数，默认 20
   * @param {number} k - 标准差倍数，默认 2
   * @returns {{ MB: number[], UB: number[], LB: number[] }}
   */
  const calcBOLL = (closeArr, n = 20, k = 2) => {
    const MB = []; // 中轨 = MA(n)
    const UB = []; // 上轨
    const LB = []; // 下轨
    for (let i = 0; i < closeArr.length; i++) {
      if (i < n - 1) {
        MB.push(null);
        UB.push(null);
        LB.push(null);
      } else {
        const slice = closeArr.slice(i - (n - 1), i + 1);
        const sum = slice.reduce((a, b) => a + b, 0);
        const ma = sum / n;
        // 计算标准差
        const variance =
          slice.reduce((acc, v) => acc + (v - ma) * (v - ma), 0) / n;
        const sd = Math.sqrt(variance);
        MB.push(parseFloat(ma.toFixed(4)));
        UB.push(parseFloat((ma + k * sd).toFixed(4)));
        LB.push(parseFloat((ma - k * sd).toFixed(4)));
      }
    }
    return { MB, UB, LB };
  };

  // ─────────────────────────────────────────────────────────────
  // 获取并处理分钟线数据
  useEffect(() => {
    if (!symbol) return;
    const chart = echarts.init(chartRef.current);
    chartInstance.current = chart;

    const fetchData = async () => {
      setLoading(true);
      chart.showLoading();

      try {
        // 假设接口返回的 data 每项为 { time, open, high, low, close, volume }
        const data = await $fetchAStockMinute({ symbol, period });
        if (!Array.isArray(data) || data.length === 0) {
          throw new Error('后端返回数据为空或格式不对');
        }
        setMinuteData(data);
      } catch (err) {
        console.error('⛔ 分时拉取失败', err);
        message.error('获取数据失败，请检查输入的股票代码或网络');
      } finally {
        chart.hideLoading();
        setLoading(false);
      }
    };

    fetchData();

    const onResize = () => chart.resize();
    window.addEventListener('resize', onResize);
    return () => {
      window.removeEventListener('resize', onResize);
      chart.dispose();
      chartInstance.current = null;
    };
  }, [symbol, period]);

  // ─────────────────────────────────────────────────────────────
  // 当分钟数据或指标勾选变化时，重新绘制图表
  useEffect(() => {
    const chart = chartInstance.current;
    if (!chart || minuteData.length === 0) return;

    // 1. 准备基础数据
    const times = minuteData.map((d) => d.time);
    const opens = minuteData.map((d) => d.open);
    const highs = minuteData.map((d) => d.high);
    const lows = minuteData.map((d) => d.low);
    const closes = minuteData.map((d) => d.close);
    const volumes = minuteData.map((d) => d.volume);

    // 2. 计算所有可能的指标
    // 2.1 MA
    const ma5 = calcMA(closes, 5);
    const ma10 = calcMA(closes, 10);
    const ma20 = calcMA(closes, 20);

    // 2.2 MACD
    const { DIF, DEA, MACD } = calcMACD(closes);

    // 2.3 RSI
    const rsi = calcRSI(closes, 14);

    // 2.4 KDJ
    const { K: kValues, D: dValues, J: jValues } = calcKDJ(highs, lows, closes, 9);

    // 2.5 BOLL（布林带）
    const { MB: mbArr, UB: ubArr, LB: lbArr } = calcBOLL(closes, 20, 2);

    // 3. 构造多个 Grid（子区块）及各自的 y 轴配置
    //    根据用户勾选指标决定哪些子区块需要显示
    const grids = [];
    const yAxes = [];
    const series = [];

    /** 
     * 第一格：价格 + MA/BOLL
     */
    grids.push({ top: '5%', height: indicators.includes('MACD') || indicators.includes('RSI') || indicators.includes('KDJ') ? '25%' : '75%', left: '8%', right: '5%' });
    yAxes.push({
      gridIndex: 0,
      name: '价格',
      position: 'left',
      scale: true,
      splitLine: { show: false },
      axisLabel: { color: '#999' },
    });

    // 3.1 - 收盘价用折线，如果想用蜡烛图可以替换为 type: 'candlestick'
    series.push({
      name: 'Close',
      type: 'line',
      data: closes,
      xAxisIndex: 0,
      yAxisIndex: 0,
      smooth: true,
      lineStyle: { width: 1, color: '#5470C6' },
      showSymbol: false,
    });

    // 3.2 - 如果选中 MA，就在同一区块 overlay MA5/10/20 三条线
    if (indicators.includes('MA')) {
      series.push({
        name: 'MA5',
        type: 'line',
        data: ma5,
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: { width: 1, opacity: 0.6, color: '#EE6666' },
        showSymbol: false,
      });
      series.push({
        name: 'MA10',
        type: 'line',
        data: ma10,
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: { width: 1, opacity: 0.6, color: '#91CC75' },
        showSymbol: false,
      });
      series.push({
        name: 'MA20',
        type: 'line',
        data: ma20,
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: { width: 1, opacity: 0.6, color: '#FAC858' },
        showSymbol: false,
      });
    }

    // 3.3 - 如果选中 BOLL，就在同一区块 overlay 布林带上下轨 & 中轨
    if (indicators.includes('BOLL')) {
      series.push({
        name: 'BOLL_MB',
        type: 'line',
        data: mbArr,
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: { width: 1, color: '#AAAAAA', opacity: 0.7 },
        showSymbol: false,
      });
      series.push({
        name: 'BOLL_UB',
        type: 'line',
        data: ubArr,
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: { width: 1, color: '#888888', opacity: 0.7 },
        showSymbol: false,
      });
      series.push({
        name: 'BOLL_LB',
        type: 'line',
        data: lbArr,
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: { width: 1, color: '#888888', opacity: 0.7 },
        showSymbol: false,
      });
    }

    /** 
     * 第二格：MACD
     */
    if (indicators.includes('MACD')) {
      grids.push({ top: '35%', height: (indicators.includes('RSI') || indicators.includes('KDJ')) ? '15%' : '35%', left: '8%', right: '5%' });
      yAxes.push({
        gridIndex: grids.length - 1,
        name: 'MACD',
        position: 'left',
        scale: true,
        splitLine: { show: false },
        axisLabel: { color: '#999' },
      });

      // DIF
      series.push({
        name: 'DIF',
        type: 'line',
        data: DIF,
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        lineStyle: { width: 1, color: '#EE6666' },
        showSymbol: false,
      });
      // DEA
      series.push({
        name: 'DEA',
        type: 'line',
        data: DEA,
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        lineStyle: { width: 1, color: '#5470C6' },
        showSymbol: false,
      });
      // MACD 柱状
      series.push({
        name: 'MACD_Hist',
        type: 'bar',
        data: MACD.map((v) => (v == null ? 0 : v)),
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        itemStyle: {
          color: (params) => (params.value >= 0 ? '#26A69A' : '#EF5350'),
        },
      });
    }

    /** 
     * 第三格：RSI
     */
    if (indicators.includes('RSI')) {
      grids.push({ top: indicators.includes('MACD') ? (indicators.includes('KDJ') ? '55%' : '50%') : '35%', height: (indicators.includes('KDJ') ? '15%' : '35%'), left: '8%', right: '5%' });
      yAxes.push({
        gridIndex: grids.length - 1,
        name: 'RSI(14)',
        position: 'left',
        scale: true,
        splitLine: { show: false },
        axisLabel: { color: '#999' },
      });

      series.push({
        name: 'RSI',
        type: 'line',
        data: rsi,
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        lineStyle: { width: 1, color: '#FF9800' },
        showSymbol: false,
      });
    }

    /** 
     * 第四格：KDJ
     */
    if (indicators.includes('KDJ')) {
      grids.push({ top: '75%', height: '20%', left: '8%', right: '5%' });
      yAxes.push({
        gridIndex: grids.length - 1,
        name: 'KDJ',
        position: 'left',
        scale: true,
        splitLine: { show: false },
        axisLabel: { color: '#999' },
      });

      series.push({
        name: 'K',
        type: 'line',
        data: kValues,
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        lineStyle: { width: 1, color: '#FFEB3B' },
        showSymbol: false,
      });
      series.push({
        name: 'D',
        type: 'line',
        data: dValues,
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        lineStyle: { width: 1, color: '#03A9F4' },
        showSymbol: false,
      });
      series.push({
        name: 'J',
        type: 'line',
        data: jValues,
        xAxisIndex: grids.length - 1,
        yAxisIndex: grids.length - 1,
        lineStyle: { width: 1, color: '#E91E63' },
        showSymbol: false,
      });
    }

    // —— 构造 X 轴（所有子区块共享一个时间轴）
    const xAxes = grids.map((_, idx) => ({
      gridIndex: idx,
      type: 'category',
      data: times,
      axisLabel: { show: idx === grids.length - 1 }, // 只有最后一个显示刻度文本
      axisLine: { onZero: false, lineStyle: { color: '#888' } },
      axisTick: { show: false },
      splitLine: { show: false },
    }));

    // —— 体积图放最底层 overlay（可选）
    //    体积也可以放在第一格或一个单独的区块，这里示例放在第一格右侧独立轴
    series.push({
      name: 'Volume',
      type: 'bar',
      data: volumes,
      xAxisIndex: 0,
      yAxisIndex: 0,
      barWidth: '60%',
      itemStyle: { color: '#B0BEC5', opacity: 0.5 },
      z: -1,
    });

    // —— 最终 option
    const option = {
      backgroundColor: '#fff',
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'cross' },
      },
      legend: {
        top: 0,
        left: 10,
        data: series.map((s) => s.name),
        textStyle: { fontSize: 12 },
      },
      grid: grids,
      xAxis: xAxes,
      yAxis: yAxes,
      dataZoom: [
        {
          type: 'inside',
          xAxisIndex: Array.from({ length: grids.length }, (_, i) => i),
          start: 0,
          end: 100,
        },
        {
          show: true,
          xAxisIndex: Array.from({ length: grids.length }, (_, i) => i),
          type: 'slider',
          bottom: '0%',
          start: 0,
          end: 100,
        },
      ],
      series: series,
    };

    chart.setOption(option, true);
    chart.resize();
  }, [minuteData, indicators]);

  return (
    <Card
      className="stock-minute-indicators-chart"
      title="A 股/指数 分时图 + 技术指标"
      extra={
        <>
          <Search
            placeholder="输入股票代码"
            allowClear
            enterButton="搜索"
            onSearch={(value) => {
              if (!value.trim()) {
                message.warning('请输入有效的股票代码');
                return;
              }
              setSymbol(value.trim());
            }}
            style={{ width: 240, marginRight: 12 }}
          />
          <Select
            defaultValue={period}
            onChange={(v) => setPeriod(v)}
            style={{ width: 100, marginRight: 12 }}
          >
            <Option value="1">1 分钟</Option>
            <Option value="5">5 分钟</Option>
            <Option value="15">15 分钟</Option>
            <Option value="30">30 分钟</Option>
            <Option value="60">60 分钟</Option>
          </Select>
          <Checkbox.Group
            options={INDICATORS}
            value={indicators}
            onChange={(checked) => setIndicators(checked)}
          />
        </>
      }
    >
      <Spin spinning={loading} tip="加载中..." className="spin-center">
        <div ref={chartRef} className="chart-container" />
      </Spin>
    </Card>
  );
};

export default StockMinuteWithIndicators;
